home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 11 / Mac Magazin and MacEasy Magazine CD - Issue 11.iso / Sharewarebibliothek / Entwickler / WASTE 1.1b1 Distribution / Demo Source / WETabs.p < prev   
Text File  |  1995-06-01  |  9KB  |  350 lines

  1. unit WETabs;
  2.  
  3. { Hooks for adding tab support to WASTE }
  4.  
  5. { Original C code by Mark Alldritt }
  6. { Line breaking code by Dan Crevier }
  7. { Support for horizontal scrolling by Bert Seltzer }
  8. { Pascal port by Marco Piovanelli, February 1995 }
  9.  
  10. interface
  11.     uses
  12.         WASTE;
  13.  
  14.     function WEInstallTabHooks (hWE: WEHandle): OSErr;
  15.     function WERemoveTabHooks (hWE: WEHandle): OSErr;
  16.     function WEIsTabHooks (hWE: WEHandle): Boolean;
  17.  
  18. implementation
  19.     uses
  20.         ToolUtils;
  21.  
  22.     const
  23.  
  24.         kOneToOneScaling = $00010001;            { 1:1 scaling ratio }
  25.         kTab = 9;
  26.         kTabWidth = 32;
  27.  
  28.     var
  29.  
  30. { static variables }
  31.  
  32.         sDrawTextHook: WEDrawTextUPP;
  33.         sPixelToCharHook: WEPixelToCharUPP;
  34.         sCharToPixelHook: WECharToPixelUPP;
  35.         sLineBreakHook: WELineBreakUPP;
  36.  
  37.     procedure _WETabDrawText (pText: Ptr;
  38.                                     textLength: LongInt;
  39.                                     slop: Fixed;
  40.                                     styleRunPosition: JustStyleCode;
  41.                                     hWE: WEHandle);
  42.         var
  43.             destRect: LongRect;
  44.             ii, beginChar: LongInt;
  45.             tabWidth: Integer;
  46.             penPos: Point;
  47.     begin
  48.         WEGetDestRect(destRect, hWE);
  49.  
  50.         beginChar := 0;
  51.         for ii := 0 to textLength - 1 do
  52.             begin
  53.                 if (Ptr(LongInt(pText) + ii)^ = kTab) then
  54.                     begin
  55.                         DrawText(pText, beginChar, ii - beginChar);
  56.  
  57. { advance the pen to the next tab stop }
  58.                         GetPen(penPos);
  59.                         tabWidth := kTabWidth - (Integer(penPos.h - destRect.left) mod kTabWidth);
  60.                         MoveTo(penPos.h + tabWidth, penPos.v);
  61.                         beginChar := ii + 1;
  62.                     end;
  63.             end;  { for }
  64.  
  65.         DrawText(pText, beginChar, textLength - beginChar);
  66.     end;  { _WETabDrawText }
  67.  
  68.     function _WETabPixelToChar (pText: Ptr;
  69.                                     textLength: LongInt;
  70.                                     slop: Fixed;
  71.                                     var width: Fixed;
  72.                                     var edge: SignedByte;
  73.                                     styleRunPosition: JustStyleCode;
  74.                                     hPos: Fixed;
  75.                                     hWE: WEHandle): LongInt;
  76.         var
  77.             ii, beginChar, offset: LongInt;
  78.             lastWidth, tabWidth: Fixed;
  79.             tempPoint: Point;
  80.     begin
  81.         beginChar := 0;
  82.         offset := 0;
  83.         tempPoint := Point(kOneToOneScaling);
  84.  
  85. { loop through every character in the segment looking for tabs }
  86.         for ii := 0 to textLength - 1 do
  87.             begin
  88.  
  89. { exit now if width has gone negative (i.e. if we have found which glyph was hit) }
  90.                 if (width <= 0) then
  91.                     Leave;
  92.  
  93. { tab found? }
  94.                 if (Ptr(LongInt(pText) + ii)^ = kTab) then
  95.                     begin
  96.  
  97. { calculate the width of the sub-segment preceding the tab }
  98.                         lastWidth := width;
  99.                         offset := offset + PixelToChar(Ptr(LongInt(pText) + beginChar), ii - beginChar, slop, lastWidth, Boolean(edge), width, styleRunPosition, tempPoint, tempPoint);
  100.                         beginChar := ii + 1;
  101.  
  102. { hit point past sub-segment? }
  103.                         if (width >= 0) then
  104.                             begin
  105.  
  106. { increment hPos by width of sub-segment preceding the tab }
  107.                                 hPos := hPos + (lastWidth - width);
  108.  
  109. { calculate the width of the tab "glyph" (as a Fixed value) }
  110.                                 tabWidth := BSL(kTabWidth - (FixRound(hPos) mod kTabWidth), 16);
  111.  
  112. { increment hPos by width of tab character }
  113.                                 hPos := hPos + tabWidth;
  114.  
  115. { hit point within tab glyph? }
  116.                                 if (width < tabWidth) then
  117.                                     begin
  118.  
  119. { yes: determine which half of tab glyph was hit }
  120.                                         if (width > tabWidth div 2) then
  121.                                             begin
  122.                                                 edge := kTrailingEdge;        { second (trailing) half of tab }
  123.                                                 offset := offset + 1;
  124.                                             end
  125.                                         else
  126.                                             edge := kLeadingEdge;            { first (leading) half of tab }
  127.  
  128. { returning -1 (as Fixed) in width means we're finished }
  129.                                         width := $FFFF0000;
  130.  
  131.                                     end
  132.                                 else
  133.                                     begin
  134.  
  135. { hit point is past tab: go on looping }
  136.                                         offset := offset + 1;
  137.                                         width := width - tabWidth;
  138.                                     end;
  139.                             end;  { if width >= 0 }
  140.                     end;  { if tab found }
  141.             end;  { for }
  142.  
  143. { no more tabs in this segment: process the last sub-segment }
  144.         if (width >= 0) then
  145.             begin
  146.                 lastWidth := width;
  147.                 offset := offset + PixelToChar(Ptr(LongInt(pText) + beginChar), textLength - beginChar, slop, lastWidth, Boolean(edge), width, styleRunPosition, tempPoint, tempPoint);
  148.             end;
  149.  
  150. { round width to nearest integer value }
  151. { (this is supposed to fix an incompatibility with the WorldScript Power Adapter) }
  152.         width := BSL(FixRound(width), 16);
  153.  
  154. { return offset }
  155.         _WETabPixelToChar := offset;
  156.  
  157.     end;  { _WETabPixelToChar }
  158.  
  159.     function _WETabCharToPixel (pText: Ptr;
  160.                                     textLength: LongInt;
  161.                                     slop: Fixed;
  162.                                     offset: LongInt;
  163.                                     direction: Integer;
  164.                                     styleRunPosition: JustStyleCode;
  165.                                     hPos: LongInt;
  166.                                     hWE: WEHandle): Integer;
  167.         var
  168.             destRect: LongRect;
  169.             ii, beginChar: LongInt;
  170.             width, totalWidth: Integer;
  171.     begin
  172.         WEGetDestRect(destRect, hWE);
  173.         beginChar := 0;
  174.         totalWidth := 0;
  175.  
  176. { measure text up to offset, if offset is within this segment }
  177.         if (offset < textLength) then
  178.             textLength := offset;
  179.  
  180.         for ii := 0 to textLength - 1 do
  181.             begin
  182.                 if (Ptr(LongInt(pText) + ii)^ = kTab) then
  183.                     begin
  184.  
  185. { calculate the pixel width of the subsegment preceding the tab }
  186.                         width := TextWidth(pText, beginChar, ii - beginChar);
  187.                         totalWidth := totalWidth + width;
  188.                         hPos := hPos + width;
  189.  
  190. { calculate tab width }
  191.                         width := kTabWidth - (Integer(hPos - destRect.left) mod kTabWidth);
  192.                         totalWidth := totalWidth + width;
  193.                         hPos := hPos + width;
  194.  
  195. { go to next subsegment }
  196.                         beginChar := ii + 1;
  197.                     end;
  198.             end;  { for }
  199.  
  200. { calculate width of remaining characters }
  201.         width := TextWidth(pText, beginChar, textLength - beginChar);
  202.         totalWidth := totalWidth + width;
  203.         _WETabCharToPixel := totalWidth;
  204.     end;  { _WETabCharToPixel }
  205.  
  206.     function _WETabLineBreak (pText: Ptr;
  207.                                     textLength: LongInt;
  208.                                     textStart: LongInt;
  209.                                     textEnd: LongInt;
  210.                                     var textWidth: Fixed;
  211.                                     var textOffset: LongInt;
  212.                                     hWE: WEHandle): StyledLineBreakCode;
  213.         var
  214.             destRect: LongRect;
  215.             ii, beginChar: LongInt;
  216.             tabWidth: Fixed;
  217.             breakCode: StyledLineBreakCode;
  218.     begin
  219.         WEGetDestRect(destRect, hWE);
  220.         breakCode := smBreakOverflow;
  221.         beginChar := textStart;
  222.  
  223.         for ii := textStart to textEnd - 1 do
  224.             begin
  225.                 if (Ptr(LongInt(pText) + ii)^ = kTab) then
  226.                     begin
  227.  
  228. { do previous "segment" }
  229.                         breakCode := StyledLineBreak(pText, textLength, beginChar, ii, 0, textWidth, textOffset);
  230.                         if ((breakCode <> smBreakOverflow) or (ii >= textLength)) then
  231.                             Leave;
  232.  
  233.                         beginChar := ii + 1;
  234.  
  235. { calculate tab width (as a Fixed value) }
  236.                         tabWidth := BSL(kTabWidth - ((Integer(destRect.right - destRect.left) - FixRound(textWidth)) mod kTabWidth), 16);
  237.  
  238. { if tabWidth > pixelWidth we break in tab }
  239. { don't move tab to next line }
  240.                         if (tabWidth > textWidth) then
  241.                             begin
  242.                                 breakCode := smBreakWord;
  243.                                 textOffset := ii + 1;
  244.                                 Leave;
  245.                             end
  246.                         else
  247.  
  248. { subtract tab width from pixel width }
  249.                             textWidth := textWidth - tabWidth;
  250.                     end;  { if tab }
  251.             end;  { for }
  252.  
  253. { do last sub-segment }
  254.         if ((ii - beginChar >= 0) and (breakCode = smBreakOverflow)) then
  255.  
  256. { do the styled break }
  257.             breakCode := StyledLineBreak(pText, textLength, beginChar, ii, 0, textWidth, textOffset);
  258.  
  259. { return break code }
  260.         _WETabLineBreak := breakCode;
  261.  
  262.     end;  { _WETabLineBreak }
  263.  
  264.     function WEInstallTabHooks (hWE: WEHandle): OSErr;
  265.         label
  266.             1;
  267.         var
  268.             err: OSErr;
  269.     begin
  270.  
  271. { create routine descriptors }
  272.         if (sDrawTextHook = nil) then
  273.             begin
  274.                 sDrawTextHook := NewWEDrawTextProc(@_WETabDrawText);
  275.                 sPixelToCharHook := NewWEPixelToCharProc(@_WETabPixelToChar);
  276.                 sCharToPixelHook := NewWECharToPixelProc(@_WETabCharToPixel);
  277.                 sLineBreakHook := NewWELineBreakProc(@_WETabLineBreak);
  278.             end;
  279.  
  280. { install the text drawing hook }
  281.         err := WESetInfo(weDrawTextHook, @sDrawTextHook, hWE);
  282.         if (err <> noErr) then
  283.             goto 1;
  284.  
  285. { install the PixelToChar hook }
  286.         err := WESetInfo(wePixelToCharHook, @sPixelToCharHook, hWE);
  287.         if (err <> noErr) then
  288.             goto 1;
  289.  
  290. { install the CharToPixel hook }
  291.         err := WESetInfo(weCharToPixelHook, @sCharToPixelHook, hWE);
  292.         if (err <> noErr) then
  293.             goto 1;
  294.  
  295. { install the line break hook }
  296.         err := WESetInfo(weLineBreakHook, @sLineBreakHook, hWE);
  297.  
  298. 1:
  299. { return result code }
  300.         WEInstallTabHooks := err;
  301.  
  302.     end;  { WEInstallTabHooks }
  303.  
  304.     function WERemoveTabHooks (hWE: WEHandle): OSErr;
  305.         label
  306.             1;
  307.         var
  308.             hook: ProcPtr;
  309.             err: OSErr;
  310.     begin
  311.         hook := nil;
  312.  
  313. { remove the text drawing hook }
  314.         err := WESetInfo(weDrawTextHook, @hook, hWE);
  315.         if (err <> noErr) then
  316.             goto 1;
  317.  
  318. { remove the PixelToChar hook }
  319.         err := WESetInfo(wePixelToCharHook, @hook, hWE);
  320.         if (err <> noErr) then
  321.             goto 1;
  322.  
  323. { remove the CharToPixel hook }
  324.         err := WESetInfo(weCharToPixelHook, @hook, hWE);
  325.         if (err <> noErr) then
  326.             goto 1;
  327.  
  328. { remove the line break hook }
  329.         err := WESetInfo(weLineBreakHook, @hook, hWE);
  330.  
  331. 1:
  332. { return result code }
  333.         WERemoveTabHooks := err;
  334.  
  335.     end;  { WERemoveTabHooks }
  336.  
  337.     function WEIsTabHooks (hWE: WEHandle): Boolean;
  338.         var
  339.             hook: ProcPtr;
  340.     begin
  341.         if (sDrawTextHook <> nil) then
  342.  
  343. { return TRUE if our tab hooks are installed }
  344.             WEIsTabHooks := (WEGetInfo(weDrawTextHook, @hook, hWE) = noErr) & (hook = sDrawTextHook)
  345.         else
  346.             WEIsTabHooks := false;
  347.  
  348.     end;  { WEIsTabHooks }
  349.  
  350. end.